package com.demo.algorithm.HouseRobber07;

/**
 * Author:       zhangshaoyang
 * Description: 首尾也算相邻
 * 你是一个专业的小偷，计划偷窃沿街的房屋，每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ，这意味着第一个房屋和最后一个房屋是紧挨着的。同时，相邻的房屋装有相互连通的防盗系统，如果两间相邻的房屋在同一晚上被小偷闯入，系统会自动报警 。
 * <p>
 * 给定一个代表每个房屋存放金额的非负整数数组，计算你 在不触动警报装置的情况下 ，今晚能够偷窃到的最高金额。
 * <p>
 *
 * <p>
 * 示例 1：
 * <p>
 * 输入：nums = [2,3,2]
 * 输出：3
 * 解释：你不能先偷窃 1 号房屋（金额 = 2），然后偷窃 3 号房屋（金额 = 2）, 因为他们是相邻的。
 * 示例 2：
 * <p>
 * 输入：nums = [1,2,3,1]
 * 输出：4
 * 解释：你可以先偷窃 1 号房屋（金额 = 1），然后偷窃 3 号房屋（金额 = 3）。
 * 偷窃到的最高金额 = 1 + 3 = 4 。
 * 示例 3：
 * <p>
 * 输入：nums = [0]
 * 输出：0
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/house-robber-ii
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 * Date:         2021/7/15 3:49 下午
 */
public class HouseRobber2 {

    /**
     * 首先，首尾房间不能同时被抢，那么只可能有三种不同情况：要么都不被抢；要么第一间房子被抢最后一间不抢；要么最后一间房子被抢第一间不抢。
     * 那就简单了啊，这三种情况，那种的结果最大，就是最终答案呗！
     * 不过，其实我们不需要比较三种情况，只要比较情况二和情况三就行了，因为这两种情况对于房子的选择余地比情况一大呀，房子里的钱数都是非负数，所以选择余地大，最优决策结果肯定不会小。
     *
     * @param nums
     * @return
     */
    public static int rob(int[] nums) {
        int n = nums.length;
        if (n == 1) return nums[0];
        return Math.max(
                robRange(nums, 0, n - 2),
                robRange(nums, 1, n - 1));
    }

    //仅计算闭区间[start,end]的最优结果
    public static int robRange(int[] nums, int start, int end) {
        int dp_i1 = 0, dp_i2 = 0;
        int dp_i = 0;
        for (int i = end; i >= start; i--) {
//            System.out.print("start = " + start);
//            System.out.print(" end = " + end);
//            System.out.println(" ----> nums[" + end + "] = " + nums[end]);
//            System.out.println("dp_i1 = " + dp_i1);
//            System.out.println("dp_i2 = " + dp_i2);
            dp_i = Math.max(dp_i1, nums[i] + dp_i2);
//            System.out.println("dp_i = " + dp_i);
            dp_i2 = dp_i1;
            dp_i1 = dp_i;
        }
        return dp_i;
    }

    public static void main(String[] args) {
        int[] nums = {1, 2, 3, 1};
        int[] nums1 = {2, 3, 2};
        int rob = rob(nums);
//        int rob1 = rob(nums1);
        System.out.println(rob);
//        System.out.println(rob1);
    }
}
